LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;


ENTITY cores_enviroment IS
GENERIC (
            cores      : natural := 1
        );
Port(
        clk		             : IN STD_LOGIC;
        
        datain            : IN unsigned(7 downto 0);  
        datain_valid      : IN std_logic;
        module_enable	    : IN std_logic;
                   
        --sram read interface
        sram_read_addr    : in std_logic_vector(17 DOWNTO 0);
        sram_read_data    : in std_logic_vector(15 DOWNTO 0);
        sram_read_valid   : IN std_logic;
        grant_read        : IN std_logic;  
        grant_valid_read  : IN std_logic;
        request_out_read  : out std_logic;
        request_addr_read : out std_logic_vector(17 DOWNTO 0); 
        --sram write interface
        grant_write            : IN std_logic;  
        grant_valid_write      : IN std_logic;
        request_out_write      : out std_logic;
        request_data_write     : out std_logic_vector(15 DOWNTO 0);
        request_addr_write     : out std_logic_vector(17 DOWNTO 0)
);
END cores_enviroment;


ARCHITECTURE bhv OF cores_enviroment IS

   signal sram_read_addr_buffer     : std_logic_vector(17 DOWNTO 0);
   signal sram_read_data_buffer     : std_logic_vector(15 DOWNTO 0);
   signal sram_read_valid_buffer    : std_logic := '0';

   signal read_request : unsigned (cores-1 downto 0);
   signal read_request_addr : std_logic_vector((cores*18)-1 downto 0);
   
   signal start_schedule_read     : std_logic;
   signal schedule_nr_read        : std_logic_vector (cores-1 DOWNTO 0);
   signal scheduling_done_read    : std_logic;
   
   
   signal write_request : unsigned (cores-1 downto 0);
   signal write_request_addr : std_logic_vector((cores*18)-1 downto 0);
   signal write_request_data : std_logic_vector((cores*16)-1 downto 0);
   
   signal write_request_ack : std_logic_vector(cores-1 downto 0);
   
   signal start_schedule_write     : std_logic;
   signal schedule_nr_write        : std_logic_vector (cores-1 DOWNTO 0);
   signal scheduling_done_write    : std_logic;
   
   
   signal control_enable  : unsigned(cores-1 downto 0);   
   

   component core_32 IS
   PORT
   (    clk		              : IN STD_LOGIC;
        reset              : IN STD_LOGIC;
                   
        sram_read_addr     : in std_logic_vector(17 DOWNTO 0);
        sram_read_data     : in std_logic_vector(15 DOWNTO 0);
        sram_read_valid    : IN std_logic;
        read_request       : out std_logic;
        read_request_addr  : out std_logic_vector(17 downto 0);
        
        write_request : out std_logic;
        write_request_addr : out std_logic_vector(17 downto 0);
        write_request_data : out std_logic_vector(15 downto 0);
        write_request_ack : in std_logic
   );
   END component;
   

   component arbiter IS
    GENERIC(
       num_requester      : natural := 4
    );
    PORT( 
       clk                : IN   std_logic;
       request            : IN   unsigned (num_requester-1 DOWNTO 0);
       start_schedule     : IN   std_logic;
       schedule_nr        : OUT   std_logic_vector (num_requester-1 DOWNTO 0);
       scheduling_done    : OUT   std_logic           
    );
   end component;
   
   
   component core_read_mux IS
   GENERIC (
            cores      : natural := 1
          );
   PORT( 
       clk                : IN std_logic;  
       grant              : IN std_logic;  
       grant_valid        : IN std_logic;
       sram_read_addr     : in std_logic_vector(17 DOWNTO 0);
       sram_read_valid    : IN std_logic;
       request_sram       : out std_logic;
       request_addr       : out std_logic_vector(17 DOWNTO 0);
       read_request_addr  : in  std_logic_vector((cores*18)-1 downto 0);
       start_schedule     : out  std_logic;
       schedule_nr        : in   std_logic_vector (cores-1 DOWNTO 0);
       scheduling_done    : in   std_logic    
    );
   end component;
   
   
   component core_write_mux IS
   GENERIC (
            cores      : natural := 1
          );
   PORT( 
       clk                : IN std_logic;  
       grant              : IN std_logic;  
       grant_valid        : IN std_logic;
       request_out        : out std_logic;
       request_data       : out std_logic_vector(15 DOWNTO 0);
       request_addr       : out std_logic_vector(17 DOWNTO 0);
       write_request_addr : in std_logic_vector((cores*18)-1 downto 0); 
       write_request_data : in std_logic_vector((cores*16)-1 downto 0);
       write_request_ack  : out std_logic_vector(cores-1 downto 0);
       start_schedule     : out  std_logic;
       schedule_nr        : in   std_logic_vector (cores-1 DOWNTO 0);
       scheduling_done    : in   std_logic           
    );
    end component;



BEGIN
	
	
   core : for i in 1 to cores generate
	 design : core_32
   PORT map
   (
      clk		             => clk,
      reset             => control_enable(i-1),
      sram_read_addr    => sram_read_addr_buffer,
      sram_read_data    => sram_read_data_buffer,
      sram_read_valid   => sram_read_valid_buffer,
      read_request      => read_request(i-1),
      read_request_addr => read_request_addr((i*18)-1 downto (i-1)*18),
      write_request     => write_request(i-1),
      write_request_addr=> write_request_addr((i*18)-1 downto (i-1)*18),
      write_request_data=> write_request_data((i*16)-1 downto (i-1)*16),
      write_request_ack => write_request_ack(i-1)
   );
   end generate core;

   
   
   arbiter_read : arbiter 
   generic map(
     num_requester      => cores
   )
   port map ( 
     clk                => clk,
     request            => read_request,
     start_schedule     => start_schedule_read,
     schedule_nr        => schedule_nr_read,
     scheduling_done    => scheduling_done_read      
   );
   

   core_read_mux1 : core_read_mux
   generic map(
     cores      => cores
   )
   PORT map( 
       clk                => clk,  
       grant              => grant_read,
       grant_valid        => grant_valid_read,
       sram_read_addr     => sram_read_addr,
       sram_read_valid    => sram_read_valid,
       request_sram       => request_out_read,
       request_addr       => request_addr_read,
       read_request_addr  => read_request_addr,
       start_schedule     => start_schedule_read,
       schedule_nr        => schedule_nr_read,
       scheduling_done    => scheduling_done_read 
    );
    
    
    
    arbiter_write : arbiter 
    generic map(
     num_requester      => cores
    )
    port map ( 
     clk                => clk,
     request            => write_request,
     start_schedule     => start_schedule_write,
     schedule_nr        => schedule_nr_write,
     scheduling_done    => scheduling_done_write      
    );
    

    
    core_write_mux1 :core_write_mux
    GENERIC map (
            cores      => cores
          )
    PORT map( 
       clk                => clk,
       grant              => grant_write,
       grant_valid        => grant_valid_write,
       request_out        => request_out_write,
       request_data       => request_data_write,
       request_addr       => request_addr_write,
       write_request_addr => write_request_addr,
       write_request_data => write_request_data,
       write_request_ack  => write_request_ack,
       start_schedule     => start_schedule_write,
       schedule_nr        => schedule_nr_write,
       scheduling_done    => scheduling_done_write        
    );
   
   
   process (clk)
   begin
    if rising_edge(clk) then
      sram_read_addr_buffer     <= sram_read_addr;
      sram_read_data_buffer     <= sram_read_data;
      sram_read_valid_buffer    <= sram_read_valid;
	  end if;
	 end process;
	 
	 control_enable <= datain(cores-1 downto 0) when module_enable='1' and datain_valid='1' else (cores-1 downto 0 => '0');

END bhv;










